﻿using System;
using System.Collections.Generic;
using ParserGenerator.Collections;
using ParserGenerator.GrammarConstruction;

namespace ParserGenerator.ParserConstruction
{
    [Serializable]
    public sealed class ParserAutomatonReductionLookaheadSet : ReadOnlySet<GrammarTerminalSymbol>
    {
        public ParserAutomatonReduction Reduction { get; }
        public ParserAutomatonState State => Reduction.State;
        public ParserAutomatonItem Item => Reduction.Item;
        public GrammarProduction Production => Reduction.Production;
        internal ISet<GrammarTerminalSymbol> UnderlyingSet => Set;

        internal ParserAutomatonReductionLookaheadSet(ParserAutomatonReduction reduction)
            : this(reduction, new HashSet<GrammarTerminalSymbol>())
        {
        }

        internal ParserAutomatonReductionLookaheadSet(ParserAutomatonReduction reduction, ISet<GrammarTerminalSymbol> set)
            : base(set)
        {
            if (reduction == null)
                throw new ArgumentNullException(nameof(reduction));
            Reduction = reduction;
        }

        internal bool Add(GrammarTerminalSymbol token)
        {
            if (token == null)
                throw new ArgumentNullException(nameof(token));
            return Set.Add(token);
        }

        internal void UnionWith(IEnumerable<GrammarTerminalSymbol> collection)
        {
            if (collection == null)
                throw new ArgumentNullException(nameof(collection));
            var set = collection as ParserAutomatonReductionLookaheadSet;
            if (set != null)
            {
                Set.UnionWith(set.Set);
                return;
            }
            var set2 = collection as ParserAutomatonItemLookaheadSet;
            if (set2 != null)
            {
                Set.UnionWith(set2.UnderlyingSet);
                return;
            }
            Set.UnionWith(collection);
        }
    }
}
